﻿/***************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@gmail.com)

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/

using System;
using System.Drawing;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using WebGridView = System.Web.UI.WebControls.GridView;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using BaoJianSoft.Common;
using BaoJianSoft.Membership;
using BaoJianSoft.Web.Extensions.Controls;

namespace BaoJianSoft.Web.Extensions.DynamicPages
{
	/// <summary>
	/// Template of field header.
	/// </summary>
	public class FieldHeaderTemplate : ITemplate
	{
		private string headerText;
		private GridViewPanel gridViewPanelHolder;

		/// <summary>
		/// Construct FieldHeaderTemplate Template
		/// </summary>
		/// <param name="gridViewPanelHolder">GridView panel control holder</param>
		/// <param name="headerText">Field header text</param>
		public FieldHeaderTemplate(GridViewPanel gridViewPanelHolder, string headerText)
		{
			this.gridViewPanelHolder = gridViewPanelHolder;
			this.headerText = headerText;
		}

		/// <summary>
		/// When implemented by a class, defines the System.Web.UI.Control object that child controls and templates belong to. 
		/// These child controls are in turn defined within an inline template.
		/// </summary>
		/// <param name="container"></param>
		public void InstantiateIn(Control container)
		{
			DataControlFieldHeaderCell headerCell = container as DataControlFieldHeaderCell;
			headerCell.Wrap = false;
			if (!Kit.IsEmpty(headerCell.ContainingField.SortExpression))
			{
				headerCell.Attributes["onmouseover"] = "var accessor = $(this); if (accessor.attr(\"class\") != \"gridviewheader_sorting\") accessor.attr(\"class\", \"gridviewheader_mouseover\")";
				headerCell.Attributes["onmouseout"] = "var accessor = $(this); if (accessor.attr(\"class\") != \"gridviewheader_sorting\") accessor.attr(\"class\", \"gridviewheader_mouseout\")";
				headerCell.Attributes["onclick"] = "var accessor = $(\"a\", this); var href = accessor.attr(\"href\"); accessor.attr(\"href\", \"#\"); eval(href);";

				string linkButtonId = headerCell.ContainingField.SortExpression;
				//linkButtonId = ResolveLinkButtonId(linkButtonId);
				LinkButton linkButton = new LinkButton() { ID = linkButtonId, CommandArgument = headerCell.ContainingField.SortExpression };
				headerCell.Controls.Add(linkButton);

				IAuthenticationContext authenticationContext = SpringContext.Current.GetObject<IAuthenticationContext>();
				SortingField currentSortingField = authenticationContext[HttpContext.Current.Request.Url.ToString()] as SortingField;

				if (currentSortingField != null && currentSortingField.SortExpression == headerCell.ContainingField.SortExpression)
				{
					SortDirection reversedSortDirection = (currentSortingField.SortDirection == SortDirection.Ascending) ? SortDirection.Descending : SortDirection.Ascending;
					Label label = new Label { Text = this.headerText };
					System.Web.UI.WebControls.Image sortingImage = new System.Web.UI.WebControls.Image { ImageUrl = ResolveSortingIcon(currentSortingField.SortDirection) };
					sortingImage.Style["vertical-align"] = "middle";
					sortingImage.Style["padding-left"] = "2px";

					HtmlTable htmlTable = new HtmlTable();
					htmlTable.Style["padding"] = "0";
					htmlTable.Style["margin"] = "0";
					htmlTable.Style["line-height"] = "20px";
					htmlTable.Style["cursor"] = "pointer";
					HtmlTableRow htmlTableRow = new HtmlTableRow();
					htmlTable.Controls.Add(htmlTableRow);

					HtmlTableCell htmlTableCell = new HtmlTableCell("td");
					htmlTableCell.Style["padding"] = "0";
					htmlTableCell.Style["margin"] = "0";
					htmlTableCell.NoWrap = true;
					htmlTableCell.Controls.Add(label);
					htmlTableRow.Controls.Add(htmlTableCell);

					htmlTableCell = new HtmlTableCell("td");
					htmlTableCell.Style["padding"] = "0";
					htmlTableCell.Style["margin"] = "0";
					htmlTableCell.NoWrap = true;
					htmlTableCell.Controls.Add(sortingImage);
					htmlTableRow.Controls.Add(htmlTableCell);

					linkButton.Controls.Add(htmlTable);

					headerCell.CssClass = "gridviewheader_sorting";
					linkButton.CommandName = reversedSortDirection.ToString();
				}
				else
				{
					linkButton.Text = this.headerText;

					SortingField historySortingField = authenticationContext[linkButton.ID] as SortingField;
					if (historySortingField == null)
						linkButton.CommandName = SortDirection.Descending.ToString();
					else
						linkButton.CommandName = (historySortingField.SortDirection == SortDirection.Ascending) ? SortDirection.Descending.ToString() : SortDirection.Ascending.ToString();
				}

				linkButton.Command += (sender, arg) =>
					{
						string sortExpression = arg.CommandArgument.ToString();
						SortDirection sortDirection = (SortDirection)Enum.Parse(typeof(SortDirection), arg.CommandName);

						LinkButton linkButtonSorting = sender as LinkButton;
						SortingField sortingField = new SortingField { SortExpression = sortExpression, SortDirection = sortDirection };
						authenticationContext[linkButtonSorting.ID] = sortingField;
						authenticationContext[HttpContext.Current.Request.Url.ToString()] = sortingField;

						(sender as LinkButton).CommandName = (sortDirection == SortDirection.Ascending) ? SortDirection.Descending.ToString() : SortDirection.Ascending.ToString();
						this.gridViewPanelHolder.OnGridViewSorting(sender, new GridViewSortEventArgs(sortExpression, sortDirection));
					};

				WebUtility.RegisterAsyncPostBackControl(linkButton);
			}
			else
			{
				headerCell.Controls.Add(new Label { Text = this.headerText });
			}
		}

		private string ResolveLinkButtonId(string linkButtonId)
		{
			return this.ResolveLinkButtonId(linkButtonId, 0);
		}

		private string ResolveLinkButtonId(string linkButtonId, int duplicateIndex)
		{
			string returnedLinkButtonId = string.Concat(linkButtonId, duplicateIndex == 0 ? "" : "__" + duplicateIndex.ToString());
			string variableName = string.Format("FieldHeaderTemplate.LinkButton.{0}", returnedLinkButtonId);
			if (!this.gridViewPanelHolder.Variables.ContainsKey(variableName))
			{
				this.gridViewPanelHolder.Variables.Add(variableName, returnedLinkButtonId);
				return returnedLinkButtonId;
			}
			else
			{
				return this.ResolveLinkButtonId(linkButtonId, duplicateIndex + 1);
			}
		}

		private static string ResolveSortingIcon(SortDirection sortDirection)
		{
			Page webpage = HttpContext.Current.Handler as Page;
			return string.Format("~/App_Themes/{0}/Controls/GridViewPanel/{1}", webpage.Theme, sortDirection == SortDirection.Ascending ? "up.gif" : "down.gif");
		}

		/// <summary>
		/// Class presents sorting field.
		/// </summary>
		[Serializable]
		public class SortingField
		{
			/// <summary>
			/// Sets/gets sort expression
			/// </summary>
			public string SortExpression { get; set; }

			/// <summary>
			/// Sets/gets sort direction.
			/// </summary>
			public SortDirection SortDirection { get; set; }
		}
	}
}

